package com.zx.sdk.league.member;

import android.app.Activity;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.zx.sdk.StrategyHelper;
import com.zx.sdk.ZxSDK;
import com.zx.sdk.listener.BaseZxBannerListener;
import com.zx.sdk.listener.BaseZxRewardListener;
import com.zx.sdk.listener.BaseZxShortVideoListener;
import com.zx.sdk.listener.BaseZxSplashListener;
import com.zx.sdk.model.AdInfo;
import com.zx.sdk.model.ReadyAdPosition;
import com.zx.sdk.util.LogHelper;
import com.zx.sdk.util.RunnableHelper;
import com.zx.sdk.util.UiHelper;
import com.zx.sdk.util.ZxEventHelper;
import com.zx.sdk.view.widget.BaseNewsAdView;

import java.util.HashMap;

/*广告联盟成员基类*/
public abstract class BaseLeagueMember<S, R, B, I, F> {
    protected Context context;
    protected String mobAppId;//成员平台appId
    protected boolean initialized = false;
    protected final HashMap<String, S> splashMap = new HashMap<>();//开屏广告加载Map
    protected final HashMap<String, R> rewardMap = new HashMap<>();//激励视频广告加载Map
    protected final HashMap<String, I> interstitialMap = new HashMap<>();//插屏广告加载Map
    protected final HashMap<String, B> bannerMap = new HashMap<>();//插屏广告加载Map
    protected final HashMap<String, F> suspensionMap = new HashMap<>();//悬浮广告广告加载Map
    protected final HashMap<String, Integer> cpmCache = new HashMap<>();// 缓存bid广告位的报价，为事件提供报价参数

    /*成员名称*/
    public abstract String getName();

    /*初始化*/
    private void init(Context context, String mobAppId) {
//        LogHelper.d("联盟=" + getName() ," 开始初始化 mobAppId = " + mobAppId);
        BaseLeagueMember.this.context = context;
        BaseLeagueMember.this.mobAppId = mobAppId;
        onInit(context, mobAppId, initialized);
        initialized = true;
    }

    /*初始化模板方法*/
    protected abstract void onInit(Context context, String appId, boolean initialized);

    /*加载Splash广告*/
    public final void loadSplash(Context context, AdInfo adInfo, ViewGroup container, String mode, String type, BaseZxSplashListener listener) {
        RunnableHelper.tryRun(() -> init(context, adInfo.getMapAppid()));
        ZxEventHelper.record(ZxSDK.SPLASH, ZxEventHelper.FETCH, adInfo, this);
        LogHelper.d(getName(), "开始加载Splash广告", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
        RunnableHelper.runOnUIThread(() -> onLoadSplash(adInfo, container, mode, type, listener));
    }

    /*加载Splash广告模板方法*/
    protected abstract void onLoadSplash(AdInfo adInfo, ViewGroup container, String mode, String type, BaseZxSplashListener listener);

    /*加载完成存储Splash广告*/
    public void saveSplash(String pid, S splash, ViewGroup container) {
//        if (isSplashContainerNotVisible(container)) {
//            LogHelper.d("联盟=" + getName(), "因为Splash广告的容器不可见，缓存的广告不存入MAP appId = " + mobAppId + " pid =" + pid);
//            return;
//        }
        splashMap.put(pid, splash);
        LogHelper.d("联盟=" + getName(), "加载Splash完成并缓存", "appId=" + mobAppId, "pid=" + pid);
    }

    /**
     * 开屏广告的容器是否消失
     */
    public boolean isSplashContainerNotVisible(ViewGroup container) {
        return container == null || container.getVisibility() == View.GONE || container.getVisibility() == View.INVISIBLE || container.getParent() == null;
    }

    /*显示Splash广告*/
    public boolean showSplash(AdInfo adInfo, ViewGroup container, BaseZxSplashListener listener) {
        if (isSplashContainerNotVisible(container)) {
            LogHelper.d("联盟=" + getName(), "因为Splash广告的容器不可见，这次不显示 appId = " + mobAppId + " pid =" + adInfo.getMapPid());
            return false;
        }
        LogHelper.e("联盟=" + getName(), " 开始显示Splash广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid(), adInfo.getAdType() + "");
        S splash = splashMap.remove(adInfo.getMapPid());//如果拿出来的广告显示成功或者失败，都不需要继续留在Map里。
        ZxSDK.destroySplash((Activity) container.getContext(), true);
        ZxSDK.shownSplash.put(getName(), splash);
        if (onShowSplash(adInfo, container, splash, listener)) {
            LogHelper.d("联盟=" + getName(), " 显示Splash广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());
            return true;
        }
        return false;
    }

    /*显示Splash广告模板方法*/
    public abstract boolean onShowSplash(AdInfo adInfo, ViewGroup container, @Nullable S splash, BaseZxSplashListener listener);

    /*加载Splash广告*/
    public final void loadReward(Activity context, AdInfo adInfo, String mode, String type, BaseZxRewardListener listener) {
        adInfo.setToken(ZxSDK.getToken());
        LogHelper.d(getName(), "开始加载Reward广告", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
        RunnableHelper.tryRun(() -> init(context, adInfo.getMapAppid()));
        ZxEventHelper.record(ZxSDK.REWARD, ZxEventHelper.FETCH, adInfo, this);
        onLoadReward(context, adInfo, mode, type, listener);
    }

    /**
     * 获取已经填充的 激励视频 实例
     *
     * @param pid pid
     */
    public R getFilledRewardByPid(String pid) {
        return rewardMap.get(pid);
    }

    /**
     * 清空已经填充的 bidding 实例，下一次预加载时还会 bidding 竞价
     *
     * @param pid pid
     */
    public void clearFilledBiddingAd(String type, String pid) {
        if (ZxSDK.REWARD.equals(type)) {
            rewardMap.remove(pid);
        } else if (ZxSDK.SPLASH.equals(type)) {
            splashMap.remove(pid);
        }
    }

    /**
     * 返回当前广告资源的cpm
     *
     * @return cpm 单位：分
     */
    public int getCpmByPid(String type, String pid) {
        return -1;
    }

    /**
     * 预加载广告资源是否就绪
     *
     * @param type ZxSDK.SPLASH | ZxSDK.REWARD
     * @param pid  pid
     * @return bool
     */
    public boolean isPreResReady(String type, String pid) {
        switch (type) {
            case ZxSDK.SPLASH:
                return splashMap.get(pid) != null;
            case ZxSDK.REWARD:
                return rewardMap.get(pid) != null;
            case ZxSDK.INTERSTITIAL:
                return interstitialMap.get(pid) != null;
            case ZxSDK.BANNER:
                return bannerMap.get(pid) != null;
        }
        return false;
    }

    public abstract void onLoadReward(Activity context, AdInfo adInfo, String mode, String type, BaseZxRewardListener listener);

    /*显示Reward广告*/
    public boolean showReward(Activity context, AdInfo adInfo, BaseZxRewardListener listener) {
        LogHelper.e("联盟=" + getName(), " 开始显示Reward广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());

        // 如果拿出来的广告显示成功或者失败，都不需要继续留在Map里。
        R reward = rewardMap.remove(adInfo.getMapPid());
        ZxSDK.destroyReward(context, true);
        ZxSDK.shownReward.put(getName(), reward);
        if (onShowReward(context, adInfo, reward, listener)) {
            LogHelper.d("联盟=" + getName(), " 显示Reward广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid(), adInfo.getAdType() + "");
            return true;
        }
        return false;
    }

    /*显示Reward广告模板方法*/
    public abstract boolean onShowReward(Activity context, AdInfo adInfo, @Nullable R reward, BaseZxRewardListener listener);

    /*加载完成存储Splash广告*/
    public void saveReward(String pid, R reward) {
        rewardMap.put(pid, reward);
        StrategyHelper.onFilledSuc(mobAppId, pid);
        LogHelper.d("联盟=" + getName(), "加载Reward广告完成并存入Map", "appId=" + mobAppId, "pid=" + pid);
    }

    public final void loadInterstitial(Activity context, AdInfo adInfo, String mode, String type, BaseZxRewardListener listener) {
        if (interstitialMap.size() > 0) {
            LogHelper.d(getName(), "开始加载Interstitial广告,但是已经有缓存了，不再继续加载", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
            return;
        }
        LogHelper.d(getName(), "开始加载Interstitial广告", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
        RunnableHelper.tryRun(() -> init(context, adInfo.getMapAppid()));
        ZxEventHelper.record(ZxSDK.INTERSTITIAL, ZxEventHelper.FETCH, adInfo, this);
        onLoadInterstitial(context, adInfo, mode, type, listener);
    }
    public abstract void onLoadInterstitial(Activity context, AdInfo adInfo, String mode, String type, BaseZxRewardListener listener);

    public final void loadBanner(Activity context, AdInfo adInfo, String mode, ViewGroup container, String type, BaseZxBannerListener listener) {
        if (bannerMap.size() > 0) {
            LogHelper.d(getName(), "开始加载Banner广告,但是已经有缓存了，不再继续加载", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
            return;
        }
        LogHelper.d(getName(), "开始加载Banner广告", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
        RunnableHelper.tryRun(() -> init(context, adInfo.getMapAppid()));
        ZxEventHelper.record(ZxSDK.BANNER, ZxEventHelper.FETCH, adInfo, this);
        onLoadBanner(context, container, adInfo, mode, type, listener);
    }

    public void loadSuspension(Activity context, AdInfo adInfo, String mode, ViewGroup container, String type, BaseZxBannerListener listener) {
        if (suspensionMap.size() > 0) {
            LogHelper.d(getName(), "开始加载Suspension广告,但是已经有缓存了，不再继续加载", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
            return;
        }
        LogHelper.d(getName(), "开始加载Suspension广告", adInfo.getMapAppid(), adInfo.getMapPid(), mode, type, adInfo.getAdType() + "");
        RunnableHelper.tryRun(() -> init(context, adInfo.getMapAppid()));
        ZxEventHelper.record(ZxSDK.SUSPENSION, ZxEventHelper.FETCH, adInfo, this);
        onLoadSuspension(context, container, adInfo, mode, type, listener);
    }

    protected void onLoadSuspension(Activity context, ViewGroup container, AdInfo adInfo, String mode, String type, BaseZxBannerListener listener) {

    }

    public void onLoadBanner(Activity context, ViewGroup container, AdInfo adInfo, String mode, String type, BaseZxBannerListener listener) {

    }

    public void saveInterstitial(String pid, I interstitial) {
        interstitialMap.put(pid, interstitial);
        StrategyHelper.onFilledSuc(mobAppId, pid);
        LogHelper.d("联盟=" + getName(), "加载Interstitial广告完成并存入Map", "appId=" + mobAppId, "pid=" + pid);
    }

    public boolean showInterstitial(Activity context, AdInfo adInfo, BaseZxRewardListener listener) {
        LogHelper.e("联盟=" + getName(), " 开始显示Interstitial广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());

        // 如果拿出来的广告显示成功或者失败，都不需要继续留在Map里。
        I reward = interstitialMap.remove(adInfo.getMapPid());
        if (onShowInterstitial(context, adInfo, reward, listener)) {
            LogHelper.d("联盟=" + getName(), " 显示Interstitial广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());
            return true;
        }
        return false;
    }

    public abstract boolean onShowInterstitial(Activity context, AdInfo adInfo, @Nullable I interstitial, BaseZxRewardListener listener);

    /*显示Reward广告*/
    public boolean showBanner(Activity context, AdInfo adInfo, ViewGroup container, BaseZxBannerListener listener) {
        LogHelper.e("联盟=" + getName(), " 开始显示Banner广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());

        // 如果拿出来的广告显示成功或者失败，都不需要继续留在Map里。
        B reward = bannerMap.remove(adInfo.getMapPid());
        if (onShowBanner(context, adInfo, container, reward, listener)) {
            LogHelper.d("联盟=" + getName(), " 显示Banner广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());
            return true;
        }
        return false;
    }

    public boolean showSuspension(Activity context, AdInfo adInfo, ViewGroup container, BaseZxBannerListener listener) {
        LogHelper.e("联盟=" + getName(), " 开始显示Suspension广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());

        // 如果拿出来的广告显示成功或者失败，都不需要继续留在Map里。
        F suspension = suspensionMap.remove(adInfo.getMapPid());
        if (onShowSuspension(context, adInfo, container, suspension, listener)) {
            LogHelper.d("联盟=" + getName(), " 显示Suspension广告 appId = " + mobAppId + " thirdPid = " + adInfo.getMapPid());
            return true;
        }
        return false;
    }

    protected boolean onShowSuspension(Activity context, AdInfo adInfo, ViewGroup container, F suspension, BaseZxBannerListener listener) {
        return false;
    }


    /*获取短视频*/
    public Fragment getShortVideoFragment(BaseZxShortVideoListener listener, AdInfo adInfo) {
        RunnableHelper.tryRun(() -> init(context, adInfo.getMapAppid()));
        LogHelper.d("联盟=" + getName(), " 获取短视频Fragment", "appId=" + adInfo.getMapAppid(), "pid=" + adInfo.getMapPid());
        return onGetShortVideoFragment(listener, adInfo);
    }

    /*获取短视频模板方法*/
    protected Fragment onGetShortVideoFragment(BaseZxShortVideoListener listener, AdInfo adInfo) {
        return null;
    }

    public boolean onShowBanner(Activity context, AdInfo adInfo, ViewGroup container, B banner, BaseZxBannerListener listener) {
        return false;
    }

    public void addCloseBtnToBanner(@NonNull ViewGroup container, @NonNull OnCloseBannerListener listener) {
        ImageView imageView = new ImageView(container.getContext());
        imageView.setImageResource(com.zx.sdk.R.drawable.adsuyi_icon_close);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.gravity = Gravity.END;
        container.addView(imageView, layoutParams);
        imageView.setOnClickListener(v -> listener.onClose());
        imageView.setPadding(0, UiHelper.dp2Px(5), UiHelper.dp2Px(5), 0);
    }

    public void destroySplash(Activity activity) {

    }

    public void destroyShownSplash(Activity activity, S splashAd) {
    }

    public void destroyShownReward(Activity activity, R rewardAd) {

    }

    public void destroyReward(Activity activity) {

    }

    public interface OnCloseBannerListener {
        void onClose();
    }

    /**
     * 加载完成存储Banner广告
     */
    public void saveBanner(String pid, B banner) {
        bannerMap.put(pid, banner);
        StrategyHelper.onFilledSuc(mobAppId, pid);
        LogHelper.d("联盟=" + getName(), "加载Banner完成并缓存", "appId=" + mobAppId, "pid=" + pid);
    }

    public void saveSuspension(String pid, F suspension) {
        suspensionMap.put(pid, suspension);
        StrategyHelper.onFilledSuc(mobAppId, pid);
        LogHelper.d("联盟=" + getName(), "加载Suspension完成并缓存", "appId=" + mobAppId, "pid=" + pid);
    }

    /**
     * 销毁Banner广告
     */
    public void destroyBanner(Activity activity, String pid) {
        B banner = bannerMap.remove(pid);
        if (banner != null) {
            onDestroyBanner(banner);
        }
    }

    /**
     * 子类销毁Banner广告
     */
    protected void onDestroyBanner(B banner) {

    }

    public int getCachedCpmByPid(String display, String mapPid) {
        Integer cpm = cpmCache.get(display + mapPid);
        if (cpm != null) {
            return cpm;
        }
        return -1;
    }

    /**
     * 竞胜回调
     *
     * @param type   广告类型 - 开屏、激励视频
     * @param mapPid 广告位id
     * @param loser  竞败者对象
     */
    public void notifyBiddingWin(String type, String mapPid, @Nullable ReadyAdPosition loser) throws Exception {

    }

    /**
     * 竞败回调
     *
     * @param type   广告类型 - 开屏、激励视频
     * @param mapPid 广告位id
     * @param winner 竞胜者对象
     * @param reason 竞败原因
     */
    public void notifyBiddingLose(String type, String mapPid, ReadyAdPosition winner, ZxSDK.LoseReason reason) throws Exception {

    }

    final public BaseNewsAdView getNewsView(Context context, AdInfo adInfo) {
        LogHelper.d("联盟", getName(), " 获取新闻资讯", "appId", adInfo.getMapAppid(), "pid", adInfo.getMapPid());
        return onGetNewsView(context, adInfo);
    }

    protected BaseNewsAdView onGetNewsView(Context context, AdInfo adInfo) {
        return null;
    }
}
